﻿/*
    This file is part of nDoctor Light

    NDoctor is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    NDoctor is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with NDoctor.  If not, see <http://www.gnu.org/licenses/>.
*/
namespace Probel.Ldoc.ViewModels.ToolBoxes
{
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Input;

    using Probel.Ldoc.Services.Dto;
    using Probel.Ldoc.Services.Exceptions;
    using Probel.Ldoc.Services.Services;
    using Probel.Ldoc.ViewModels.Properties;
    using Probel.Mvvm.DataBinding;
    using Probel.Mvvm.Gui;

    public class MacroEditorViewModel : BaseViewModel
    {
        #region Fields

        private readonly ICommand addNewMacroCommand;
        private readonly ICommand removeMacroCommand;
        private readonly ICommand saveMacroCommand;
        private readonly IPatientService Service;

        private MacroDto currentScript;

        #endregion Fields

        #region Constructors

        public MacroEditorViewModel(IErrorService errorService, IPatientService service, PatientCardDto patient, bool isAsync = true)
            : base(errorService, isAsync)
        {
            this.CurrentPatient = patient;
            this.Service = service;
            this.Macros = new ObservableCollection<MacroDto>();

            this.addNewMacroCommand = new RelayCommand(this.AddNewMacro);
            this.removeMacroCommand = new RelayCommand(this.RemoveMacro, this.CanRemoveMacro);
            this.saveMacroCommand = new RelayCommand(this.SaveMacro, this.CanSaveMacro);
        }

        #endregion Constructors

        #region Properties

        public ICommand AddNewMacroCommand
        {
            get { return this.addNewMacroCommand; }
        }

        public MacroDto CurrentMacro
        {
            get { return this.currentScript; }
            set
            {
                this.currentScript = value;
                this.OnPropertyChanged(() => CurrentMacro);
            }
        }

        public ObservableCollection<MacroDto> Macros
        {
            get;
            private set;
        }

        public ICommand RemoveMacroCommand
        {
            get { return this.removeMacroCommand; }
        }

        public ICommand SaveMacroCommand
        {
            get { return this.saveMacroCommand; }
        }

        private PatientCardDto CurrentPatient
        {
            get;
            set;
        }

        #endregion Properties

        #region Methods

        public void Refresh()
        {
            var macros = this.Service.GetAllMacro();
            this.Macros.Refill(macros);
        }

        public string Resolve(string script)
        {
            try
            {
                return this.Service.ResolveMacro(script, this.CurrentPatient);
            }
            catch (InvalidMacroException)
            {
                this.ErrorService.HandleWarning(Messages.Msg_InvalidMacro);
                return Messages.Msg_InvalidMacro;
            }
        }

        private void AddNewMacro()
        {
            this.Service.CreateNewMacro();
            this.Refresh();
        }

        private bool CanRemoveMacro()
        {
            return this.CurrentMacro != null;
        }

        private bool CanSaveMacro()
        {
            return this.CurrentMacro != null
                && this.Service.IsMacroValid(this.CurrentMacro);
        }

        private void RemoveMacro()
        {
            var delete = ViewService.MessageBox.Question(Messages.Msg_AskDeleteMacro);

            if (delete)
            {
                this.Service.Remove(this.CurrentMacro);
                this.Refresh();
            }
        }

        private void SaveMacro()
        {
            var id = this.CurrentMacro.Id;
            this.Service.Update(this.CurrentMacro);
            this.Refresh();

            //Reselect the current macro.
            this.CurrentMacro = (from m in this.Macros
                                 where m.Id == id
                                 select m).SingleOrDefault();

            ViewService.MessageBox.Information(Messages.Msg_Saved);
        }

        #endregion Methods
    }
}